package cll;

import java.util.Collection;
import static cll.Parameters.*;
import java.util.LinkedList;

public class Environment {
	Collection<Cell> cells;
	Collection<Cell> selectedcells;
	Place[][] germinalCenter;
	
	public Environment(){
		cells = new LinkedList<Cell>();
		selectedcells =  new LinkedList<Cell>();
		germinalCenter = new Place[tailleGC][tailleGC] ;
		
		setChemokines();
		updateGradient();
		
		
	}
	public void vit() {
		
			for (Cell c : cells){
				c.move();
				c.changeDirection();
				c.dealWithChemokine();
				c.transition();
			}
			
			LinkedList<Cell> auxCells = new LinkedList<Cell>();
			for (Cell c1 : cells){
				for(Cell c2 : auxCells){
					if (proximite(c1,c2)){
						c1.interaction(c2);
					}
				}
				auxCells.add(c1);
			}
			
			auxCells = new LinkedList<Cell>();
			for (Cell c : cells){
				auxCells.add(c.Reproduction());
				auxCells.add(c.transforme());		
				}
			cells.addAll(auxCells);
			
			auxCells = new LinkedList<Cell>();
			for (Cell c : cells){
				if (c.isDead()) {auxCells.add(c);}
				if(c.type==Type.OutputCell){auxCells.add(c);selectedcells.add(c);}
			}
			cells.removeAll(auxCells);
			auxCells.clear();
		
		
		
	}
	private boolean proximite(Cell c1, Cell c2) {
		
		return (PositionSpeed.distance(c1,c2) < ( c1.getSize() + c2.getSize()));
	}
	
	// concentration nulle au départ.
	public void setChemokines(){
		/*for(int i = 0; i<tailleGC;i++){
			for(int j = 0; j<tailleGC/3;j++){
				germinalCenter[i][j] 
						= new Place(j,tailleGC-j,j);
			}
			for(int j = tailleGC/3; j<2*tailleGC/3;j++){
				germinalCenter[i][j] 
						= new Place(j,tailleGC-j,tailleGC/3);
			}
			for(int j = 2*tailleGC/3; j<tailleGC;j++){
				germinalCenter[i][j] 
						= new Place(j,tailleGC-j,tailleGC-j);
			}
		}*/
		for(int i = 0; i<tailleGC;i++){
			for(int j = 0; j<tailleGC/3;j++){
				germinalCenter[i][j] 
						= new Place(
								quantite_initiale_chemokine,
								quantite_initiale_chemokine*j*2/tailleGC,
								
								0);
			}
			for(int j = tailleGC/3; j<2*tailleGC/3;j++){
				germinalCenter[i][j] 
						= new Place(
								quantite_initiale_chemokine-quantite_initiale_chemokine*j*2/tailleGC,
								quantite_initiale_chemokine*j*2/tailleGC,
								
								0);
			}
			for(int j = 2*tailleGC/3; j<tailleGC;j++){
				germinalCenter[i][j] 
						= new Place(
								quantite_initiale_chemokine-quantite_initiale_chemokine*j*2/tailleGC,
								quantite_initiale_chemokine,
								
								0);
			}
		}
	}
	
	// gradient correspondant
	

	public Place getPlace(PositionSpeed positionspeed) {
		if ((positionspeed.x < tailleGC ) & (positionspeed.x > 0 )&(positionspeed.y>0 )&(positionspeed.y < tailleGC)){
			return germinalCenter[(int)(positionspeed.x)][(int)(positionspeed.y)];
		}
		return null;
	}
	
	public void addCells(int nombre_de_cellules, Type type) {
		for(int k=0;k<nombre_de_cellules;k++){
			if (type == Type.Centroblast) {
				cells.add(new Centroblast(this));
			}
			if (type== Type.TCell){
				cells.add(new TCell(this));
			}
			if (type== Type.FollicularDendriticCell){
				cells.add(new FollicularDendriticCell(this));
			}
			if (type== Type.StromalCell){
				cells.add(new StromalCell(this));
			}
			if (type== Type.ReticularCell){
				cells.add(new ReticularCell(this));
			}
			if (type== Type.THelper){
				cells.add(new THelper(this));
			}
			
		}
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	///inutile pour l'instant
	public void diffuseChemokine(){
		//on copie la grille de chemokine
		Place[][] gcaux = new Place[tailleGC][tailleGC];
		for(int i = 0; i<tailleGC;i++){
			for(int j = 0; j<tailleGC;j++){
				gcaux[i][j] = new Place(germinalCenter[i][j].getChemokine13(),germinalCenter[i][j].getChemokine12(),germinalCenter[i][j].getChemokine19());
			}	
		}
		
		for(int i = 1; i<tailleGC-1;i++){
			for(int j = 1; j<tailleGC-1;j++){
				
				double quantite_initiale = gcaux[i][j].getChemokine13();
				double flux_total= 0; 
				
				flux_total += (gcaux[i][j+1].getChemokine13()-quantite_initiale)*cte_diffusion_chemo13;
				flux_total += (gcaux[i][j-1].getChemokine13()-quantite_initiale)*cte_diffusion_chemo13;
				flux_total += (gcaux[i+1][j].getChemokine13()-quantite_initiale)*cte_diffusion_chemo13;
				flux_total += (gcaux[i-1][j].getChemokine13()-quantite_initiale)*cte_diffusion_chemo13;
				
				
				germinalCenter[i][j].addChemokine13(flux_total);
				
				
			}
			
		}
		
		for(int i = 1; i<tailleGC-1;i++){
			for(int j = 1; j<tailleGC-1;j++){
				
				double quantite_initiale = gcaux[i][j].getChemokine19();
				double flux_total= 0; 
				
				flux_total += (gcaux[i][j+1].getChemokine19()-quantite_initiale)*cte_diffusion_chemo19;
				flux_total += (gcaux[i][j-1].getChemokine19()-quantite_initiale)*cte_diffusion_chemo19;
				flux_total += (gcaux[i+1][j].getChemokine19()-quantite_initiale)*cte_diffusion_chemo19;
				flux_total += (gcaux[i-1][j].getChemokine19()-quantite_initiale)*cte_diffusion_chemo19;
				
				
				germinalCenter[i][j].addChemokine19(flux_total);
				
				
			}
			
		}
		for(int i = 1; i<tailleGC-1;i++){
			for(int j = 1; j<tailleGC-1;j++){
				
				double quantite_initiale = gcaux[i][j].getChemokine12();
				double flux_total= 0; 
				
				flux_total += (gcaux[i][j+1].getChemokine12()-quantite_initiale)*cte_diffusion_chemo12;
				flux_total += (gcaux[i][j-1].getChemokine12()-quantite_initiale)*cte_diffusion_chemo12;
				flux_total += (gcaux[i+1][j].getChemokine12()-quantite_initiale)*cte_diffusion_chemo12;
				flux_total += (gcaux[i-1][j].getChemokine12()-quantite_initiale)*cte_diffusion_chemo12;
				
				
				germinalCenter[i][j].addChemokine12(flux_total);
				
				
			}
			
		}
	}
	
	public void updateGradient(){
		//cette fonction ne definit pas de gradient sur les bords
		// le gradient donne juste l'angle du gradient de quantité de chemokine
		
		for(int i = 1; i<tailleGC-1;i++){
			for(int j = 1; j<tailleGC-1;j++){
				double gradx= (germinalCenter[i+1][j].getChemokine13() - germinalCenter[i-1][j].getChemokine13())/2;
				double grady= (germinalCenter[i][j+1].getChemokine13() - germinalCenter[i][j-1].getChemokine13())/2;
				
				germinalCenter[i][j].setGradient13(gradx,grady);
			}
				
			
		}
		for(int i = 1; i<tailleGC-1;i++){
			for(int j = 1; j<tailleGC-1;j++){
				double gradx= (germinalCenter[i+1][j].getChemokine19() - germinalCenter[i-1][j].getChemokine19())/2;
				double grady= (germinalCenter[i][j+1].getChemokine19() - germinalCenter[i][j-1].getChemokine19())/2;
				
				germinalCenter[i][j].setGradient19(gradx,grady);
			}
				
			
		}
		for(int i = 1; i<tailleGC-1;i++){
			for(int j = 1; j<tailleGC-1;j++){
				double gradx= (germinalCenter[i+1][j].getChemokine12() - germinalCenter[i-1][j].getChemokine12())/2;
				double grady= (germinalCenter[i][j+1].getChemokine12() - germinalCenter[i][j-1].getChemokine12())/2;
				
				germinalCenter[i][j].setGradient12(gradx,grady);
			}
				
			
		}
		
	}
	public String affinite() {
		int nombre =0;
		double distance =0;
		for(Cell c : cells){
			if( c.type== Type.OutputCell){
				nombre++;
				distance += Antigen.distanceAbsolue(c.antigen,Antigen.getTargetAntigen());
				
			}
		}
		
		return nombre+" "+(distance/nombre);
	}


	
















	
}
